package com.duartepeixinho.P3D.Objects.Primitives 
{
	import com.duartepeixinho.P3D.Core.Geom.Face3;
	import com.duartepeixinho.P3D.Core.Math.Vector3;
	import com.duartepeixinho.P3D.Materials.Materials;
	import com.duartepeixinho.P3D.Objects.Mesh;
	/**
	 * P3D
	 * @version 0.1
	 * @author Duarte Peixinho
	 */
	public class Sphere extends Mesh
	{
		
		private var _segmentsW:uint = 8;
		private var _segmentsH:uint = 6;
		private var _radius:Number = 100;
		
		public function Sphere(material:Materials, radius:Number = 100, segmentsW:uint = 8, segmentsH:uint = 6) 
		{
			// set material
			this.material = material;
			_segmentsW = segmentsW;
			_segmentsH = segmentsH;	
			_radius = radius;	
			
			var i:Number, j:Number, k:Number;
			var iHor:Number = Math.max(3, _segmentsW);
			var iVer:Number = Math.max(2, _segmentsH);
			var aVtc:Array = new Array();
			
			for (j = 0; j < (iVer + 1); j++) {
				var fRad1:Number = Number(j / iVer);
				var fZ:Number = -radius * Math.cos(fRad1 * Math.PI);
				var fRds:Number = radius * Math.sin(fRad1 * Math.PI);
				var aRow:Array = new Array();
				var oVtx:Vector3;
				for (i = 0; i < iHor; i++) {
					var fRad2:Number = Number(2 * i / iHor);
					var fX:Number = fRds * Math.sin(fRad2 * Math.PI);
					var fY:Number = fRds * Math.cos(fRad2 * Math.PI);
					if (!((j == 0 || k == iVer) && i > 0)) {
						oVtx = new Vector3(fY, fZ, fX);
						geometry.vertices.push(oVtx);
					}
					aRow.push(oVtx);
					
				}
				aVtc.push(aRow);	
				
			}
			
			var iVerNum:int = aVtc.length;
			
			for (j = 0; j < iVerNum; j++) {
				var iHorNum:int = aVtc[j].length;				
				if (j > 0) {
					for (i = 0; i < iHorNum; i++) {
						var bEnd:Boolean = i == (iHorNum - 1);
						var aP1:Number = search(aVtc[j][bEnd?0:(i + 1)]);
						var aP2:Number = search(aVtc[j][(bEnd?(iHorNum-1):i)]);
						var aP3:Number = search(aVtc[j - 1][(bEnd?(iHorNum - 1):i)]);
						var aP4:Number = search(aVtc[j - 1][bEnd?0:(i + 1)]);
						
						if (j < (aVtc.length - 1))	geometry.faces.push( new Face3(this, aP1, aP2, aP3, new Vector3(), material));
						if (j > 1)					geometry.faces.push( new Face3(this, aP1, aP3, aP4, new Vector3(), material));						
					}
				}
			}
			geometry.calcNormal();
		}
		private function search(needle:Vector3):Number {
			for (var i:uint = 0; i < geometry.vertices.length; i++) {				
				if (needle.compareVec(geometry.vertices[i])) {
					return i;				
				}
			}			
			return -1;
		}
	}
}
